// RectWindow.cpp
// by Charles Mc Auley
// "Programming AutoCAD 2000 with ObjectARX"
//
// In this application we demonstrate how to add/retrieve
// Xrecord to the Extension Dictionary of an entity. We
// demonstrate how to add data to the Xrecord and also
// how to retrieve data back from the Xrecord that is
// attached to the entites Extension Dictionary.
//
/////////////////////////////////////////////////////////


#include "StdArx.h"

RectWindow::RectWindow()
{
	// Initialize the rect Frame Thickness
	// and the internal Window Framing thickness

	rows = 1;
	cols = 1;
	rectFrameLen = 0.0;
	rectFrameHt	 = 0.0;

	lowLeftPt.set(0.0, 0.00);
}

RectWindow::~RectWindow()
{
	// Does nothing
}


void RectWindow::drawWindow(AcDbBlockTableRecord* pBlkTableRecord)
{
	AcGePoint2dArray outrFrame;
	AcDbPolyline* pFrame;
	AcDbObjectId plineId;
	AcGeVector2d vec;
	AcGePoint2d ll, lr, ur, ul;
	AcGePoint2d vrtxPt;
	double len, ht;
	Acad::ErrorStatus es;

	// Get the window length, height and start point
	len = getWindowLength();
	ht	= getWindowHeight();
	ll	= getWindowStartPoint();

	// Calculate the other 3 corner points
	// from ll
	vec.set(len, 0);
	lr = ll + vec;
	vec.set(0, ht);
	ur = lr + vec;
	ul = ll + vec;

	// Add the four calculated points to the array
	outrFrame.append(ll);
	outrFrame.append(lr);
	outrFrame.append(ur);
	outrFrame.append(ul);

	pFrame = new AcDbPolyline(4);

	for(int count = 0; count < outrFrame.length(); count++)
	{
		vrtxPt = outrFrame.at(count);
		pFrame->addVertexAt(count, vrtxPt);
	}

	pFrame->setClosed(Adesk::kTrue);

	es = pBlkTableRecord->appendAcDbEntity(plineId, pFrame);
	if(es != Acad::eOk)
	{
		ads_printf("\nError in drawing window frame. ");
		if(pFrame != NULL)
		{
			delete pFrame;
		}

		return;
	}

	pFrame->close();

	return;
}


// Get and Set functions

int RectWindow::getWindowRows() const
{
	return rows;
}

int RectWindow::getWindowCols() const
{
	return cols;
}

double RectWindow::getWindowHeight() const
{
	return rectFrameHt;
}

double RectWindow::getWindowLength() const
{
	return rectFrameLen;
}

AcGePoint2d RectWindow::getWindowStartPoint() const
{
	return lowLeftPt;
}


void RectWindow::setWindowRows(int rowQty)
{
	rows = rowQty;
}

void RectWindow::setWindowCols(int colQty)
{
	cols = colQty;
}

void RectWindow::setWindowHeight(double windHeight)
{
	rectFrameHt = windHeight;
}

void RectWindow::setWindowLength(double windLength)
{
	rectFrameLen = windLength;
}


void RectWindow::setWindowStartPoint(AcGePoint2d lowLeftPoint)
{
	lowLeftPt = lowLeftPoint;
}

void RectWindow::addXtnData()
{
    AcDbXrecord *pXrec = new AcDbXrecord;
    AcDbObject *pObj;
    AcDbObjectId dictObjId, xrecObjId, entId;
    AcDbDictionary* pDict;

	char windotype[] = {"Rect"};
	ads_name ename;
	struct resbuf* prbXtn;

	AcGePoint2d sp(getWindowStartPoint());

	ads_point lwrleft;
	lwrleft[X] = sp.x;
	lwrleft[Y] = sp.y;
	lwrleft[Z] = 0.0;

	
	// Get the last entity
	ads_entlast(ename);
	// Get the entity object ID
	acdbGetObjectId(entId, ename);

	// Open the enity for a write operation
	acdbOpenObject(pObj, entId, AcDb::kForWrite);

	pObj->createExtensionDictionary();
    dictObjId = pObj->extensionDictionary();
    pObj->close();

    acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
    pDict->setAt("WINDO_INFO", pXrec, xrecObjId);
    pDict->close();

	prbXtn = ads_buildlist(AcDb::kDxfText, windotype,
						   AcDb::kDxfInt32, getWindowRows(),
						   AcDb::kDxfInt32, getWindowCols(),
						   AcDb::kDxfReal, getWindowLength(),
						   AcDb::kDxfReal, getWindowHeight(),
						   AcDb::kDxfXCoord, lwrleft,
						   RTNONE);

	// Add the data list to the Xrecord.  Notice that this
    // member function takes a reference to resbuf *NOT* a
    // pointer to resbuf, so you must dereference the
    // pointer before sending it.
    // 
    pXrec->setFromRbChain(*prbXtn);
    pXrec->close();

	ads_relrb(prbXtn);
}

void RectWindow::printXtnData()
{
    AcDbObject *pObj;
    AcDbXrecord *pXrec;
    AcDbObjectId dictObjId, entId;
    AcDbDictionary *pDict;
	ads_name ename;
    struct resbuf *prbXtn;
	struct resbuf *pTemp;

	// Get the last entity
	ads_entlast(ename);
	// Get the entity object ID
	acdbGetObjectId(entId, ename);

	// Open the enity for a write operation
	acdbOpenObject(pObj, entId, AcDb::kForRead);

    // get the objectId of the object's extension dictionary
    //
    dictObjId = pObj->extensionDictionary();
    pObj->close();

    // Open the extension dictionary and get the xrecord
    // associated with the key "ASDK_XREC1"
    // 
    acdbOpenObject(pDict, dictObjId, AcDb::kForRead);
    pDict->getAt("WINDO_INFO", (AcDbObject*&)pXrec, AcDb::kForRead);
    pDict->close();

    // get the Xrecord's data list then close the Xrecord
    pXrec->rbChain(&prbXtn);
    pXrec->close();

	// Print out the extension dictionary data
	// Here I know the order of the  extension dictionary data
	pTemp = prbXtn;

	ads_printf("\nWindow Type = %s", pTemp->resval.rstring);

	pTemp = pTemp->rbnext;
	ads_printf("\nRows = %d", pTemp->resval.rint);

	pTemp = pTemp->rbnext;
	ads_printf("\nCols = %d", pTemp->resval.rint);

	pTemp = pTemp->rbnext;
	ads_printf("\nLength = %.2lf", pTemp->resval.rreal);

	pTemp = pTemp->rbnext;
	ads_printf("\nHeight = %.2lf", pTemp->resval.rreal);

	pTemp = pTemp->rbnext;
	ads_printf("\nStart Point = (%.2lf, %.2lf)", pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y]);
	
    ads_relrb(prbXtn);
}
